home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fspdev / fspdevPfs.c < prev    next >
C/C++ Source or Header  |  1991-06-26  |  43KB  |  1,211 lines

  1. /*
  2.  * fsPfs.c --
  3.  *
  4.  *    Routines specific to the pseudo-filesystem implementation.
  5.  *    The pseudo-filesystem server uses the same request response
  6.  *    protocol as with pseudo-devices.  The overall stream setup is
  7.  *    a bit different, however.  The server process gets back a
  8.  *    "naming" stream when it opens a remote link with the FS_PFS_MASTER
  9.  *    flag.  The kernel forwards naming operations (Fs_Open, Fs_Remove,
  10.  *    Fs_MakeDir, Fs_RemoveDir, Fs_MakeDevice, Fs_Rename, Fs_Hardlink)
  11.  *    to the server using the request response protocol over the
  12.  *    naming stream.  Thus the naming stream is like the server stream
  13.  *    returned to pseudo-device servers via its control stream, and the
  14.  *    client side of the naming stream is hung off the prefix table.
  15.  *
  16.  *    The pseudo-filesystem server can either return a pseudo-device
  17.  *    kind of connection in response to opens by clients, or it can
  18.  *    return a stream to a regular file or device.  Also, the server
  19.  *    can be private to a host, or it can export itself to the network.
  20.  *    
  21.  *
  22.  * Copyright 1987, 1988 Regents of the University of California
  23.  * Permission to use, copy, modify, and distribute this
  24.  * software and its documentation for any purpose and without
  25.  * fee is hereby granted, provided that the above copyright
  26.  * notice appear in all copies.  The University of California
  27.  * makes no representations about the suitability of this
  28.  * software for any purpose.  It is provided "as is" without
  29.  * express or implied warranty.
  30.  */
  31.  
  32. #ifndef lint
  33. static char rcsid[] = "$Header: /sprite/src/kernel/fspdev/RCS/fspdevPfs.c,v 9.3 91/06/26 01:05:59 mottsmth Exp $ SPRITE (Berkeley)";
  34. #endif not lint
  35.  
  36. #include <sprite.h>
  37. #include <fs.h>
  38. #include <fsutil.h>
  39. #include <fsNameOps.h>
  40. #include <fsio.h>
  41. #include <fsconsist.h>
  42. #include <fsdm.h>
  43. #include <fsioLock.h>
  44. #include <fsprefix.h>
  45. #include <fsStat.h>
  46. #include <proc.h>
  47. #include <rpc.h>
  48. #include <fspdev.h>
  49. #include <fspdevInt.h>
  50. #include <dev/pfs.h>
  51. #include <string.h>
  52.  
  53. static Fspdev_ServerIOHandle *PfsGetUserLevelIDs _ARGS_((
  54.     Fspdev_ServerIOHandle *pdevHandlePtr, Fs_FileID *prefixIDPtr, 
  55.     Fs_FileID *rootIDPtr));
  56.  
  57. /*
  58.  *----------------------------------------------------------------------------
  59.  *
  60.  * FspdevRmtLinkNameOpen --
  61.  *
  62.  *    The user-level server for a pseudo-filesystem is established by
  63.  *    opening a remote link type file with the FS_PFS_MASTER flag.
  64.  *    This procedure is invoked on the file server when remote links
  65.  *    are opened and detects this situation.  (If FS_PFS_MASTER is
  66.  *    not specified then Fsio_FileNameOpen is called and the remote link
  67.  *    is treated normally.)  Futhermore, there are two kinds of
  68.  *    pseudo-filesystem servers, "local agents" and "network agents".
  69.  *    If the FS_EXCLUSIVE flag is specified a local agent is created
  70.  *    and only the opening host sees the pseudo-filesystem.  Otherwise
  71.  *    the host sets up a network agent and exports the pseudo-filesystem
  72.  *    to the whole Sprite network.  In the latter case a control stream
  73.  *    is created here on the file server to record the server's existence.
  74.  *
  75.  * Results:
  76.  *    A status is returned that indicates conflict if another server exists.
  77.  *    A fileID and a streamID are also chosen for the naming stream.
  78.  *
  79.  * Side effects:
  80.  *    A control I/O handle is created here on the file server to record
  81.  *    who is the server for the pseudo device.  The handle for the
  82.  *    remote link file is unlocked.
  83.  *
  84.  *----------------------------------------------------------------------------
  85.  *
  86.  */
  87. ReturnStatus
  88. FspdevRmtLinkNameOpen(handlePtr, openArgsPtr, openResultsPtr)
  89.      register Fsio_FileIOHandle *handlePtr;    /* A handle from FslclLookup.
  90.                      * Should be LOCKED upon entry,
  91.                      * unlocked upon exit. */
  92.      Fs_OpenArgs        *openArgsPtr;    /* Standard open arguments */
  93.      Fs_OpenResults    *openResultsPtr;/* For returning ioFileID, streamID */
  94. {
  95.     register ReturnStatus status = SUCCESS;
  96.     register Fs_FileID *ioFileIDPtr = &openResultsPtr->ioFileID;
  97.  
  98.     if ((openArgsPtr->useFlags & FS_PFS_MASTER) == 0) {
  99.     return(Fsio_FileNameOpen(handlePtr, openArgsPtr, openResultsPtr));
  100.     }
  101.     /*
  102.      * Generate an ID which is just like a FSIO_CONTROL_STREAM, except that
  103.      * the serverID will be set to us, the file server, for exported
  104.      * pseudo-filesystems, or set to the host running the server if the
  105.      * pseudo-filesystem is not exported.
  106.      */
  107.     ioFileIDPtr->type = FSIO_PFS_CONTROL_STREAM;
  108.     ioFileIDPtr->major = handlePtr->hdr.fileID.major;
  109.     ioFileIDPtr->minor = handlePtr->hdr.fileID.minor ^
  110.              (handlePtr->descPtr->version << 16);
  111.     if (openArgsPtr->useFlags & FS_EXCLUSIVE) {
  112.     /*
  113.      * The pseudo-filesystem server is private to the client host.
  114.      * We further uniqify its control handle ID to avoid conflict with
  115.      * files from other servers.  We set the serverID to the host
  116.      * running the server so we won't see closes or re-opens.
  117.      */
  118.     ioFileIDPtr->serverID = openArgsPtr->clientID;
  119.     ioFileIDPtr->major ^= rpc_SpriteID << 16;
  120.     Fsio_StreamCreateID(openArgsPtr->clientID, &openResultsPtr->streamID);
  121.     } else {
  122.     /*
  123.      * The pseudo-filesystem will be exported to the network.  Setting
  124.      * the serverID of the I/O handle to us means we'll see a close
  125.      * and possibly some reopens, we can do conflict checking.  However,
  126.      * the streamID we choose is used for the server half of the naming
  127.      * request-response stream, which sort of points sideways at the
  128.      * control handle on the client.  Thus there is no shadow stream,
  129.      * only a control handle here..
  130.      */
  131.     register Fspdev_ControlIOHandle *ctrlHandlePtr;
  132.  
  133.     ioFileIDPtr->serverID = rpc_SpriteID;
  134.     ctrlHandlePtr = FspdevControlHandleInit(ioFileIDPtr, handlePtr->hdr.name);
  135.     if (ctrlHandlePtr->serverID != NIL) {
  136.         status = FS_FILE_BUSY;
  137.     } else {
  138.         ctrlHandlePtr->serverID = openArgsPtr->clientID;
  139.         Fsio_StreamCreateID(openArgsPtr->clientID, &openResultsPtr->streamID);
  140.     }
  141.     Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
  142.     }
  143.     openResultsPtr->streamData = (ClientData)NIL;
  144.     openResultsPtr->dataSize = 0;
  145.     Fsutil_HandleUnlock(handlePtr);
  146.     return(status);
  147. }
  148.  
  149. /*
  150.  *----------------------------------------------------------------------
  151.  *
  152.  * FspdevPfsIoOpen --
  153.  *
  154.  *    This is called from Fs_Open to complete setup of the stream
  155.  *    returned to the server of a pseudo-filesystem.  This stream
  156.  *    is called a "naming stream" because it will be used to
  157.  *    forward naming operations from the kernel up to the server.
  158.  *    It is structured just like the regular pseudo-device request
  159.  *    response stream, however.  The service end is returned to
  160.  *    the server and the client end is hung off the prefix table.
  161.  *
  162.  *    Note: we contrain the file name being opened to be the absolute
  163.  *    prefix of the pseudo-filesystem.  To fix this you'd need to extract
  164.  *    the prefix over at the file server and return it in the stream data.
  165.  * 
  166.  * Results:
  167.  *    SUCCESS, unless an exclusive (private) pseudo-filesystem server
  168.  *    already exists on this host.
  169.  *
  170.  * Side effects:
  171.  *    Three handles are created.  They have the same server, major, and minor,
  172.  *    but differ in their types (FSIO_PFS_CONTROL_STREAM, FSIO_SERVER_STREAM,
  173.  *    and FSIO_LCL_PSEUDO_STREAM).  The server stream is returned to our caller,
  174.  *    the client stream is hooked to the prefix table, and the control
  175.  *    stream is left around for conflict checking.
  176.  *
  177.  *----------------------------------------------------------------------
  178.  */
  179. /*ARGSUSED*/
  180. ReturnStatus
  181. FspdevPfsIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
  182.     ioHandlePtrPtr)
  183.     register Fs_FileID    *ioFileIDPtr;    /* I/O fileID */
  184.     int            *flagsPtr;    /* FS_READ | FS_WRITE ... */
  185.     int            clientID;    /* Host doing the open */
  186.     ClientData        streamData;    /* Pointer to Fspdev_State. */
  187.     char        *name;        /* File name for error msgs */
  188.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - a locked handle set up for
  189.                      * I/O to a pseudo device, or NIL */
  190. {
  191.     register ReturnStatus    status = SUCCESS;
  192.     register Fspdev_ControlIOHandle *ctrlHandlePtr;
  193.     register Fspdev_ServerIOHandle *pdevHandlePtr;
  194.     register Fspdev_ClientIOHandle *cltHandlePtr;
  195.     Fs_HandleHeader        *prefixHdrPtr;
  196.     Fs_FileID            rootID;
  197.     int                domain;
  198.     int                id;
  199.     char            *ignoredName;
  200.     Fsprefix            *prefixPtr;
  201.     int                prefixFlags;
  202.  
  203.     /*
  204.      * Constrain the name to be an absolute prefix to keep things simple.
  205.      * Then verify that the prefix is not already handled by someone.
  206.      */
  207.     if (name[0] != '/') {
  208.     printf(
  209.         "Need absolute name (not \"%s\") for pseudo-filesystem\n", name);
  210.     return(FS_INVALID_ARG);
  211.     }
  212.     status = Fsprefix_Lookup(name,
  213.         FSPREFIX_IMPORTED|FSPREFIX_EXPORTED|FSPREFIX_EXACT, -1,
  214.         &prefixHdrPtr, &rootID, &ignoredName, &id, &domain, &prefixPtr);
  215.     if (status == SUCCESS) {
  216.     printf( "Prefix \"%s\" already serviced\n", name);
  217.     return(FS_FILE_BUSY);
  218.     } else {
  219.     status = SUCCESS;
  220.     }
  221.     /*
  222.      * Nuke this meaningless flag so we don't get an I/O control from Fs_Open.
  223.      */
  224.     *flagsPtr &= ~FS_TRUNC;
  225.     /*
  226.      * Create a control handle that contains the seed used to generate
  227.      * pseudo-device connections to the pseudo-filesystem server.  It is
  228.      * important to set the serverID so the control stream won't get scavenged.
  229.      */
  230.     ctrlHandlePtr = FspdevControlHandleInit(ioFileIDPtr, name);
  231.     ctrlHandlePtr->serverID = rpc_SpriteID;
  232.     /*
  233.      * Setup the request-response connection, and return the server
  234.      * end to the calling process.  We save a back pointer to the
  235.      * control stream so we can generate new request-response connections
  236.      * when clients do opens in the pseudo-filesystem, and so we
  237.      * can close it and clean up the prefix table when the server process exits.
  238.      */
  239.     ioFileIDPtr->type = FSIO_LCL_PSEUDO_STREAM;
  240.     ioFileIDPtr->serverID = rpc_SpriteID;
  241.     cltHandlePtr = FspdevConnect(ctrlHandlePtr, ioFileIDPtr, rpc_SpriteID, 1);
  242.     if (cltHandlePtr == (Fspdev_ClientIOHandle *)NIL) {
  243.     status = FAILURE;
  244.     goto cleanup;
  245.     }
  246.     pdevHandlePtr = cltHandlePtr->pdevHandlePtr;
  247.     *ioHandlePtrPtr = (Fs_HandleHeader *)pdevHandlePtr;
  248.     /*
  249.      * This ID gets passed in Fs_LookupArgs
  250.      * as the prefixID if the prefix is the root of the pseudo domain.
  251.      * It can be reset by the user with IOC_PFS_SET_ROOT.
  252.      */
  253.     pdevHandlePtr->userLevelID.type = 0;
  254.     pdevHandlePtr->userLevelID.serverID = 0;
  255.     pdevHandlePtr->userLevelID.major = 0;
  256.     pdevHandlePtr->userLevelID.minor = 0;
  257.     /*
  258.      * Install the client side of the connection in the prefix table.
  259.      */
  260.     prefixFlags = FSPREFIX_IMPORTED;
  261.     if (*flagsPtr & FS_EXCLUSIVE) {
  262.     prefixFlags |= FSPREFIX_LOCAL;
  263.     } else {
  264.     prefixFlags |= FSPREFIX_EXPORTED;
  265.     }
  266.     ctrlHandlePtr->prefixPtr = Fsprefix_Install(name,
  267.         (Fs_HandleHeader *)cltHandlePtr, FS_PSEUDO_DOMAIN, prefixFlags);
  268.     /*
  269.      * No migration of pseudo-filesystem servers.
  270.      */
  271.     Proc_NeverMigrate(Proc_GetCurrentProc());
  272.     Fsutil_HandleUnlock(cltHandlePtr);
  273. cleanup:
  274.     if (status != SUCCESS) {
  275.     Fsutil_HandleRelease(ctrlHandlePtr, TRUE);
  276.     *ioHandlePtrPtr = (Fs_HandleHeader *)NIL;
  277.     } else {
  278.     Fsutil_HandleUnlock(ctrlHandlePtr);
  279.     }
  280.     return(status);
  281.  
  282. }
  283.  
  284. /*
  285.  *----------------------------------------------------------------------------
  286.  *
  287.  * FspdevPfsExport --
  288.  *
  289.  *    This is called from the Fsrmt_RpcPrefix stub to complete setup for
  290.  *    a client that will be importing a prefix of a pseudo-filesystem
  291.  *    that has its server process on this host.  This has to add the
  292.  *    client to the client end of the naming request response stream
  293.  *    so future naming operations by that client are accepted here.
  294.  *    The remote Sprite host will call FspdevPfsNamingIoOpen to set
  295.  *    up the handle that it will attach to its own prefix table.
  296.  *
  297.  * Results:
  298.  *    This returns a fileID that the client will use to set up its I/O handle.
  299.  *
  300.  * Side effects:
  301.  *    A control I/O handle is created here on the file server to record
  302.  *    who is the server for the pseudo device.
  303.  *
  304.  *----------------------------------------------------------------------------
  305.  *
  306.  */
  307. ReturnStatus
  308. FspdevPfsExport(hdrPtr, clientID, ioFileIDPtr, dataSizePtr, clientDataPtr)
  309.      Fs_HandleHeader    *hdrPtr;    /* A handle from the prefix table. */
  310.      int        clientID;    /* Host ID of client importing prefix */
  311.      register Fs_FileID    *ioFileIDPtr;    /* Return - I/O handle ID */
  312.      int        *dataSizePtr;    /* Return - 0 */
  313.      ClientData        *clientDataPtr;    /* Return - NIL */
  314. {
  315.     register Fspdev_ClientIOHandle *cltHandlePtr = (Fspdev_ClientIOHandle *)hdrPtr;
  316.     register ReturnStatus status;
  317.  
  318.     Fsutil_HandleLock(cltHandlePtr);
  319.     if (FspdevPdevServerOK(cltHandlePtr->pdevHandlePtr)) {
  320.     (void)Fsconsist_IOClientOpen(&cltHandlePtr->clientList, clientID, 0, FALSE);
  321.     *ioFileIDPtr = cltHandlePtr->hdr.fileID;
  322.     ioFileIDPtr->type = FSIO_PFS_NAMING_STREAM;
  323.     *dataSizePtr = 0;
  324.     *clientDataPtr = (ClientData)NIL;
  325.     status = SUCCESS;
  326.     } else {
  327.     status = FAILURE;
  328.     }
  329.     Fsutil_HandleUnlock(cltHandlePtr);
  330.     return(status);
  331. }
  332.  
  333. /*
  334.  *----------------------------------------------------------------------
  335.  *
  336.  * FspdevPfsNamingIoOpen --
  337.  *
  338.  *    This is called from FsrmtImport to complete setup of the I/O
  339.  *    handle that hangs off the prefix table.  This stream
  340.  *    is called a "naming stream" because it will be used to
  341.  *    forward naming operations to the pseudo-filesystem server.  This
  342.  *    routine is similar to FspdevRmtPseudoStreamIoOpen, except that at
  343.  *    this point the server already knows about us, so we don't have
  344.  *    to contact it with Fsrmt_DeviceOpen.
  345.  *
  346.  * Results:
  347.  *    SUCCESS.
  348.  *
  349.  * Side effects:
  350.  *    Creates a FSIO_PFS_NAMING_STREAM, which is like a FSIO_RMT_PSEUDO_STREAM
  351.  *    in that its operations are forwarded via RPC to the host running
  352.  *    the pseudo-filesystem server.
  353.  *
  354.  *----------------------------------------------------------------------
  355.  */
  356. /*ARGSUSED*/
  357. ReturnStatus
  358. FspdevPfsNamingIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
  359.     ioHandlePtrPtr)
  360.     register Fs_FileID    *ioFileIDPtr;    /* I/O fileID */
  361.     int            *flagsPtr;    /* FS_READ | FS_WRITE ... */
  362.     int            clientID;    /* Host doing the open */
  363.     ClientData        streamData;    /* Pointer to Fspdev_State. */
  364.     char        *name;        /* File name for error msgs */
  365.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - a locked handle set up for
  366.                      * I/O to a pseudo device, or NIL */
  367. {
  368.     Boolean found;
  369.     Fsrmt_IOHandle *rmtHandlePtr;
  370.  
  371.     found = Fsutil_HandleInstall(ioFileIDPtr, sizeof(Fsrmt_IOHandle), name,
  372.             FALSE, (Fs_HandleHeader **)&rmtHandlePtr);
  373.     if (!found) {
  374.     Fsutil_RecoveryInit(&rmtHandlePtr->recovery);
  375.     fs_Stats.object.remote++;
  376.     }
  377.     rmtHandlePtr->recovery.use.ref++;
  378.     *ioHandlePtrPtr = (Fs_HandleHeader *)rmtHandlePtr;
  379.     Fsutil_HandleUnlock(rmtHandlePtr);
  380.     return(SUCCESS);
  381. }
  382.  
  383. /*
  384.  *----------------------------------------------------------------------
  385.  *
  386.  * FspdevPfsDomainInfo --
  387.  *
  388.  *    Get information about a pseudo-file-system.
  389.  *
  390.  * Results:
  391.  *    An error status
  392.  *
  393.  * Side effects:
  394.  *    None.
  395.  *
  396.  *----------------------------------------------------------------------
  397.  */
  398.  
  399. ReturnStatus
  400. FspdevPfsDomainInfo(fileIDPtr, domainInfoPtr)
  401.     Fs_FileID *fileIDPtr;
  402.     Fs_DomainInfo *domainInfoPtr;
  403. {
  404.     ReturnStatus        status;
  405.     Pfs_Request            request;
  406.     Fs_RedirectInfo        *redirectPtr;
  407.     Fspdev_ClientIOHandle        *cltHandlePtr;
  408.     int                resultSize;
  409.  
  410.     status = FS_FILE_NOT_FOUND;
  411.     cltHandlePtr = Fsutil_HandleFetchType(Fspdev_ClientIOHandle, fileIDPtr);
  412.     if (cltHandlePtr != (Fspdev_ClientIOHandle *)NIL) {
  413.     Fsutil_HandleUnlock(cltHandlePtr);
  414.     /*
  415.      * Go to the pseudo-device server to get the domain information.
  416.      * We also change the fileID of the domain to be the user-visible
  417.      * one so that the getwd() library call works right.
  418.      */
  419.     *fileIDPtr = cltHandlePtr->pdevHandlePtr->userLevelID;
  420.     fileIDPtr->serverID = rpc_SpriteID;
  421.  
  422.     request.hdr.operation = PFS_DOMAIN_INFO;
  423.     request.param.domainInfo = *fileIDPtr;
  424.     resultSize = sizeof(Fs_DomainInfo);
  425.     status = FspdevPseudoStreamLookup(cltHandlePtr->pdevHandlePtr, &request,
  426.             0, (Address)NIL,
  427.             &resultSize, (Address)domainInfoPtr, &redirectPtr);
  428.     if (redirectPtr != (Fs_RedirectInfo *)NIL) {
  429.         free((Address)redirectPtr);
  430.     }
  431.     Fsutil_HandleRelease(cltHandlePtr, FALSE);
  432.     }
  433.     return(status);
  434. }
  435.  
  436.  
  437. /*
  438.  *----------------------------------------------------------------------
  439.  *
  440.  * FspdevPfsOpen --
  441.  *
  442.  *    Open a file served by a pseudo-filesystem server.  The stream returned
  443.  *    to the client can either be a pseudo-device connection to the
  444.  *    server of the pseudo-filesystem, or a regular stream that has
  445.  *    been passed off from the server process.
  446.  *
  447.  * Results:
  448.  *    SUCCESS, FS_REDIRECT, or some error code from the lookup on the server.
  449.  *    If FS_REDIRECT, then *newNameInfoPtr has prefix information.
  450.  *
  451.  * Side effects:
  452.  *    None here.  The connections are setup in the server IOControl routine.
  453.  *
  454.  *----------------------------------------------------------------------
  455.  */
  456.  
  457. ReturnStatus
  458. FspdevPfsOpen(prefixHandle, relativeName, argsPtr, resultsPtr, 
  459.          newNameInfoPtrPtr)
  460.     Fs_HandleHeader  *prefixHandle;    /* Handle from prefix table or cwd */
  461.     char       *relativeName;    /* The name of the file to open. */
  462.     Address       argsPtr;        /* Ref. to Fs_OpenArgs */
  463.     Address       resultsPtr;        /* Ref. to Fs_OpenResults */
  464.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server leaves 
  465.                      * its domain during the lookup. */
  466. {
  467.     register Fspdev_ClientIOHandle    *cltHandlePtr;
  468.     register Fspdev_ServerIOHandle *pdevHandlePtr;
  469.     register Fs_OpenArgs        *openArgsPtr = (Fs_OpenArgs *)argsPtr;
  470.     Pfs_Request            request;
  471.     register ReturnStatus    status;
  472.     int                resultSize;
  473.  
  474.     cltHandlePtr = (Fspdev_ClientIOHandle *)prefixHandle;
  475.  
  476.     /*
  477.      * Set up the open arguments, and get ahold of the naming stream.
  478.      */
  479.     request.hdr.operation = PFS_OPEN;
  480.     pdevHandlePtr = PfsGetUserLevelIDs(cltHandlePtr->pdevHandlePtr,
  481.                 &openArgsPtr->prefixID, &openArgsPtr->rootID);
  482.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  483.     return(FS_FILE_NOT_FOUND);
  484.     }
  485.     request.param.open = *openArgsPtr;
  486.  
  487.     resultSize = sizeof(Fs_OpenResults);
  488.  
  489.     /*
  490.      * Do the open.  The openResults are setup by the server-side IOC
  491.      * handler, so just we return.
  492.      */
  493.     status = FspdevPseudoStreamLookup(pdevHandlePtr, &request,
  494.         strlen(relativeName) + 1, (Address)relativeName,
  495.         &resultSize, resultsPtr, newNameInfoPtrPtr);
  496.     return(status);
  497. }
  498.  
  499. /*
  500.  *----------------------------------------------------------------------
  501.  *
  502.  * PfsGetUserLevelID --
  503.  *
  504.  *    This takes the lookup arguments for the pseudo-domain and maps them to
  505.  *    the correct request-response stream for naming, and to the user-level
  506.  *    versions of the prefix and root IDs.  Because of current directories,
  507.  *    the handle passed to the Pfs lookup routines won't always be the
  508.  *    top-level naming request-response stream.  However, we do get passed
  509.  *    the fileID of the root, from which we can fetch the right handle.
  510.  *
  511.  * Results:
  512.  *    Returns the pdevHandlePtr for the naming request-response stream.  This
  513.  *    is in turn passed to FspdevPseudoStreamLookup.  This also sets the prefixID
  514.  *    to be the user-level version.
  515.  *
  516.  * Side effects:
  517.  *    None.
  518.  *
  519.  *----------------------------------------------------------------------
  520.  */
  521.  
  522. static Fspdev_ServerIOHandle *
  523. PfsGetUserLevelIDs(pdevHandlePtr, prefixIDPtr, rootIDPtr)
  524.     Fspdev_ServerIOHandle *pdevHandlePtr;    /* Handle of name prefix */
  525.     Fs_FileID *prefixIDPtr;        /* Prefix fileID */
  526.     Fs_FileID *rootIDPtr;        /* ID of naming request-response */
  527. {
  528.     register Fspdev_ClientIOHandle *cltHandlePtr;
  529.  
  530.     *prefixIDPtr = pdevHandlePtr->userLevelID;
  531.     rootIDPtr->type = fsio_RmtToLclType[rootIDPtr->type];
  532.     cltHandlePtr = Fsutil_HandleFetchType(Fspdev_ClientIOHandle, rootIDPtr);
  533.     if (cltHandlePtr != (Fspdev_ClientIOHandle *)NIL) {
  534.     Fsutil_HandleRelease(cltHandlePtr, TRUE);
  535.     return(cltHandlePtr->pdevHandlePtr);
  536.     } else {
  537.     return((Fspdev_ServerIOHandle *)NIL);
  538.     }
  539. }
  540.  
  541. /*
  542.  *----------------------------------------------------------------------
  543.  *
  544.  * FspdevPfsOpenConnection --
  545.  *
  546.  *    This is called when the server does an IOC_PFS_OPEN to respond
  547.  *    to an open request issued by FspdevPfsOpen.  This sets up the server's
  548.  *    half of the pseudo-device connection, while FspdevPfsOpen completes
  549.  *    the connection by opening the client's half.  This knows it is
  550.  *    executing in the kernel context of the server process so it can
  551.  *    establish the user-level streamID needed by the server.
  552.  *
  553.  * Results:
  554.  *    A streamID that has to be returned to the server.
  555.  *
  556.  * Side effects:
  557.  *    Set up the state for a pseudo-device connection.
  558.  *
  559.  *----------------------------------------------------------------------
  560.  */
  561. int
  562. FspdevPfsOpenConnection(namingPdevHandlePtr, srvrFileIDPtr, openResultsPtr)
  563.     Fspdev_ServerIOHandle    *namingPdevHandlePtr;/* From naming request-response */
  564.     Fs_FileID *srvrFileIDPtr;        /* FileID from user-level server */
  565.     Fs_OpenResults *openResultsPtr;    /* Info returned to client's open */
  566. {
  567.     register Fspdev_ControlIOHandle *ctrlHandlePtr;
  568.     register Fspdev_ClientIOHandle *cltHandlePtr;
  569.     register Fs_Stream *srvStreamPtr;
  570.     register Fs_Stream *cltStreamPtr;
  571.     int newStreamID;
  572.     register Fs_FileID    *fileIDPtr;    /* FileID for new connection */
  573.  
  574.     /*
  575.      * Pick an I/O fileID for the connection.
  576.      */
  577.     ctrlHandlePtr = namingPdevHandlePtr->ctrlHandlePtr;
  578.     ctrlHandlePtr->seed++;
  579.     fileIDPtr = &openResultsPtr->ioFileID;
  580.     fileIDPtr->type = FSIO_LCL_PFS_STREAM;
  581.     fileIDPtr->serverID = rpc_SpriteID;
  582.     fileIDPtr->major = ctrlHandlePtr->rmt.hdr.fileID.major;
  583.     fileIDPtr->minor = (ctrlHandlePtr->rmt.hdr.fileID.minor << 12)
  584.             ^ ctrlHandlePtr->seed;
  585.  
  586.     cltHandlePtr = FspdevConnect(ctrlHandlePtr, fileIDPtr,
  587.             namingPdevHandlePtr->open.clientID, 0);
  588.     if (cltHandlePtr == (Fspdev_ClientIOHandle *)NIL) {
  589.     printf( "FspdevPfsOpenConnection failing\n");
  590.     return(-1);
  591.     }
  592.     /*
  593.      * Set the ioFileID type. (FspdevConnect has munged it to FSIO_SERVER_STREAM.)
  594.      * The open.clientID has been set curtesy of the PFS_OPEN RequestResponse.
  595.      */
  596.     if (namingPdevHandlePtr->open.clientID == rpc_SpriteID) {
  597.     fileIDPtr->type = FSIO_LCL_PFS_STREAM;
  598.     } else {
  599.     fileIDPtr->type = FSIO_RMT_PFS_STREAM;
  600.     }
  601.     /*
  602.      * Save the server process's ID for the connection.
  603.      */
  604.     cltHandlePtr->pdevHandlePtr->userLevelID = *srvrFileIDPtr;
  605.  
  606.     /*
  607.      * Set up a stream to the server's half of the connection and
  608.      * then choose a user level streamID.
  609.      */
  610.     srvStreamPtr = Fsio_StreamCreate(rpc_SpriteID, rpc_SpriteID,
  611.             (Fs_HandleHeader *)cltHandlePtr->pdevHandlePtr,
  612.             FS_READ|FS_USER, namingPdevHandlePtr->open.name);
  613.     if (Fs_GetStreamID(srvStreamPtr, &newStreamID) != SUCCESS) {
  614.     (void)Fsio_StreamClientClose(&srvStreamPtr->clientList, rpc_SpriteID);
  615.     Fsio_StreamDestroy(srvStreamPtr);
  616.     Sync_LockClear(&cltHandlePtr->pdevHandlePtr->lock);
  617.     Fsutil_HandleRemove(cltHandlePtr->pdevHandlePtr);
  618.     Fsutil_HandleRemove(cltHandlePtr);
  619.     fs_Stats.object.pseudoStreams--;
  620.     newStreamID = -1;
  621.     } else {
  622.     /*
  623.      * Set up a stream to the client's half of the connection.
  624.      */
  625.     cltStreamPtr = Fsio_StreamCreate(rpc_SpriteID,
  626.                 namingPdevHandlePtr->open.clientID,
  627.                 (Fs_HandleHeader *)cltHandlePtr,
  628.                 namingPdevHandlePtr->open.useFlags,
  629.                 namingPdevHandlePtr->open.name);
  630.     openResultsPtr->nameID = openResultsPtr->ioFileID;
  631.     openResultsPtr->streamID = cltStreamPtr->hdr.fileID;
  632.     openResultsPtr->dataSize = 0;
  633.     openResultsPtr->streamData = (ClientData)NIL;
  634.     Fsutil_HandleRelease(cltStreamPtr, TRUE);
  635.     Fsutil_HandleUnlock(cltHandlePtr);
  636.     Fsutil_HandleUnlock(srvStreamPtr);
  637.     }
  638.     return(newStreamID);
  639. }
  640.  
  641. /*
  642.  *----------------------------------------------------------------------
  643.  *
  644.  * FspdevPfsStreamIoOpen --
  645.  *
  646.  *    This is called from Fs_Open to complete setup of a client's
  647.  *    stream to a pseudo-filesystem server.  The server is running on this
  648.  *    host, and the pseudo-device connection has already been established.
  649.  *    This routine just latches onto it and returns.
  650.  * 
  651.  * Results:
  652.  *    SUCCESS, unless the server process has died recently.
  653.  *
  654.  * Side effects:
  655.  *    Fetches the handle, which increments its ref count.  The
  656.  *    handle is unlocked before returning.
  657.  *
  658.  *----------------------------------------------------------------------
  659.  */
  660. /*ARGSUSED*/
  661. ReturnStatus
  662. FspdevPfsStreamIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
  663.     ioHandlePtrPtr)
  664.     register Fs_FileID    *ioFileIDPtr;    /* I/O fileID */
  665.     int            *flagsPtr;    /* FS_READ | FS_WRITE ... */
  666.     int            clientID;    /* Host doing the open */
  667.     ClientData        streamData;    /* Pointer to Fspdev_State. */
  668.     char        *name;        /* File name for error msgs */
  669.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - a locked handle set up for
  670.                      * I/O to a pseudo device, or NIL */
  671. {
  672.     register Fspdev_ClientIOHandle *cltHandlePtr;
  673.  
  674.     cltHandlePtr = Fsutil_HandleFetchType(Fspdev_ClientIOHandle, ioFileIDPtr);
  675.     if (cltHandlePtr == (Fspdev_ClientIOHandle *)NIL) {
  676.     printf( "FspdevPfsStreamIoOpen, no handle\n");
  677.     *ioHandlePtrPtr = (Fs_HandleHeader *)NIL;
  678.     return(FS_FILE_NOT_FOUND);
  679.     } else {
  680.     if (cltHandlePtr->hdr.name != (char *)NIL) {
  681.         free((Address)cltHandlePtr->hdr.name);
  682.     }
  683.     cltHandlePtr->hdr.name = (char *)malloc(strlen(name) + 1);
  684.     (void)strcpy(cltHandlePtr->hdr.name, name);
  685.     *ioHandlePtrPtr = (Fs_HandleHeader *)cltHandlePtr;
  686.     if (*flagsPtr & FS_EXECUTE) {         /* Promote execute access to */
  687.         *flagsPtr |= FS_READ;          /* read access. JMS */
  688.     }
  689.     Fsutil_HandleUnlock(cltHandlePtr);
  690.     return(SUCCESS);
  691.     }
  692. }
  693.  
  694. /*
  695.  *----------------------------------------------------------------------
  696.  *
  697.  * FspdevRmtPfsStreamIoOpen --
  698.  *
  699.  *    This is called from Fs_Open to complete setup of a client's
  700.  *    stream to a remote pseudo-filesystem server.  The server is running
  701.  *    on this    host, and the pseudo-device connection has already been
  702.  *    established.  This routine just sets up a remote handle that
  703.  *    references the connection.
  704.  * 
  705.  * Results:
  706.  *    SUCCESS.
  707.  *
  708.  * Side effects:
  709.  *    Installs a remote I/O handle.
  710.  *
  711.  *----------------------------------------------------------------------
  712.  */
  713. /*ARGSUSED*/
  714. ReturnStatus
  715. FspdevRmtPfsStreamIoOpen(ioFileIDPtr, flagsPtr, clientID, streamData, name,
  716.     ioHandlePtrPtr)
  717.     register Fs_FileID    *ioFileIDPtr;    /* I/O fileID */
  718.     int            *flagsPtr;    /* FS_READ | FS_WRITE ... */
  719.     int            clientID;    /* Host doing the open */
  720.     ClientData        streamData;    /* NIL. */
  721.     char        *name;        /* File name for error msgs */
  722.     Fs_HandleHeader    **ioHandlePtrPtr;/* Return - FSIO_RMT_PFS_STREAM handle */
  723. {
  724.     Fsrmt_IOHandleInit(ioFileIDPtr, *flagsPtr, name, ioHandlePtrPtr);
  725.     if (*flagsPtr & FS_EXECUTE) {         /* Promote execute access to */
  726.     *flagsPtr |= FS_READ;             /* read access. JMS */
  727.     }
  728.     return(SUCCESS);
  729. }
  730.  
  731. /*
  732.  *----------------------------------------------------------------------
  733.  *
  734.  * FspdevPfsGetAttrPath --
  735.  *
  736.  *    Get the attributes of a file in a pseudo-filesystem.
  737.  *
  738.  * Results:
  739.  *    A return code from the RPC or the remote server.
  740.  *
  741.  * Side effects:
  742.  *    None.
  743.  *
  744.  *----------------------------------------------------------------------
  745.  */
  746. ReturnStatus
  747. FspdevPfsGetAttrPath(prefixHandle, relativeName, argsPtr, resultsPtr,
  748.                  newNameInfoPtrPtr)
  749.     Fs_HandleHeader *prefixHandle;    /* Handle from the prefix table */
  750.     char           *relativeName;    /* The name of the file. */
  751.     Address        argsPtr;        /* Bundled arguments for us */
  752.     Address        resultsPtr;        /* Where to store attributes */
  753.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server leaves 
  754.                      * its domain during the lookup. */
  755. {
  756.     register Fspdev_ServerIOHandle    *pdevHandlePtr;
  757.     Pfs_Request            request;
  758.     register ReturnStatus    status;
  759.     register Fs_OpenArgs        *openArgsPtr;
  760.     register Fs_GetAttrResults    *getAttrResultsPtr;
  761.     int                resultSize;
  762.  
  763.     pdevHandlePtr = ((Fspdev_ClientIOHandle *)prefixHandle)->pdevHandlePtr;
  764.     openArgsPtr = (Fs_OpenArgs *)argsPtr;
  765.  
  766.     request.hdr.operation = PFS_GET_ATTR;
  767.     pdevHandlePtr = PfsGetUserLevelIDs(pdevHandlePtr,
  768.                 &openArgsPtr->prefixID, &openArgsPtr->rootID);
  769.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  770.     return(FS_FILE_NOT_FOUND);
  771.     }
  772.     request.param.open = *(Fs_OpenArgs *)argsPtr;
  773.  
  774.     getAttrResultsPtr = (Fs_GetAttrResults *)resultsPtr;
  775.     resultSize = sizeof(Fs_Attributes);
  776.  
  777.     status = FspdevPseudoStreamLookup(pdevHandlePtr, &request,
  778.         strlen(relativeName) + 1, (Address)relativeName,
  779.         &resultSize, (Address)getAttrResultsPtr->attrPtr,
  780.         newNameInfoPtrPtr);
  781.     /*
  782.      * Patch the serverID in the attributes so it matches the serverID
  783.      * given in the prefix table.  This is needed to make getwd() work.
  784.      */
  785.     getAttrResultsPtr->attrPtr->serverID = rpc_SpriteID;
  786.     /*
  787.      * The pseudo-filesystem server has given us all the attributes.  There
  788.      * is no reason to do a getIOAttr so we inhibit that with a special
  789.      * ioFileID type.  However, because Fsutil_DomainInfo calls this routine
  790.      * to fill in the file ID for the user-visible prefix table entry
  791.      * we set up the rest of the fields to match the return of a stat() call.
  792.      */
  793.     getAttrResultsPtr->fileIDPtr->type = -1;
  794.     getAttrResultsPtr->fileIDPtr->serverID = getAttrResultsPtr->attrPtr->serverID;
  795.     getAttrResultsPtr->fileIDPtr->major = getAttrResultsPtr->attrPtr->domain;
  796.     getAttrResultsPtr->fileIDPtr->minor = getAttrResultsPtr->attrPtr->fileNumber;
  797.     return(status);
  798. }
  799.  
  800. /*
  801.  *----------------------------------------------------------------------
  802.  *
  803.  * FspdevPfsSetAttrPath --
  804.  *
  805.  *    Set the attributes of a file in a pseudo-filesystem.
  806.  *
  807.  * Results:
  808.  *    A return code from the RPC or the remote server.
  809.  *
  810.  * Side effects:
  811.  *    Setting those attributes.
  812.  *
  813.  *----------------------------------------------------------------------
  814.  */
  815. ReturnStatus
  816. FspdevPfsSetAttrPath(prefixHandle, relativeName, argsPtr, resultsPtr,
  817.                  newNameInfoPtrPtr)
  818.     Fs_HandleHeader *prefixHandle;    /* Handle from the prefix table */
  819.     char           *relativeName;    /* The name of the file. */
  820.     Address        argsPtr;        /* Bundled arguments for us */
  821.     Address        resultsPtr;        /* Where to store attributes */
  822.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server leaves 
  823.                      * its domain during the lookup. */
  824. {
  825.     register Fspdev_ServerIOHandle    *pdevHandlePtr;
  826.     Pfs_Request            request;
  827.     register ReturnStatus    status;
  828.     register Fs_SetAttrArgs    *setAttrArgsPtr;
  829.     register Pfs_SetAttrData    *setAttrDataPtr;
  830.     register int        nameLength;
  831.     register int        dataLength;
  832.     int                zero = 0;
  833.  
  834.     pdevHandlePtr = ((Fspdev_ClientIOHandle *)prefixHandle)->pdevHandlePtr;
  835.  
  836.     setAttrArgsPtr = (Fs_SetAttrArgs *)argsPtr;
  837.  
  838.     request.hdr.operation = PFS_SET_ATTR;
  839.     pdevHandlePtr = PfsGetUserLevelIDs(pdevHandlePtr,
  840.                 &setAttrArgsPtr->openArgs.prefixID,
  841.                 &setAttrArgsPtr->openArgs.rootID);
  842.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  843.     return(FS_FILE_NOT_FOUND);
  844.     }
  845.     request.param.open = setAttrArgsPtr->openArgs;
  846.  
  847.     /*
  848.      * The dataLength includes 4 bytes of name inside the Pfs_SetAttrData
  849.      * so there is room for the trailing null byte.
  850.      */
  851.     nameLength = strlen(relativeName);
  852.     dataLength = sizeof(Pfs_SetAttrData) + nameLength;
  853.  
  854.     setAttrDataPtr = (Pfs_SetAttrData *)malloc(dataLength);
  855.     setAttrDataPtr->attr = setAttrArgsPtr->attr;
  856.     setAttrDataPtr->flags = setAttrArgsPtr->flags;
  857.     setAttrDataPtr->nameLength = nameLength;
  858.     (void)strcpy(setAttrDataPtr->name, relativeName);
  859.  
  860.     status = FspdevPseudoStreamLookup(pdevHandlePtr, &request,
  861.         dataLength, (Address)setAttrDataPtr,
  862.         &zero, (Address)NIL, newNameInfoPtrPtr);
  863.     free((Address)setAttrDataPtr);
  864.     /*
  865.      * The pseudo-filesystem server has dealt with all the attributes so
  866.      * we don't fill in the ioFileID.
  867.      */
  868.     ((Fs_FileID *)resultsPtr)->type = -1;
  869.     return(status);
  870. }
  871.  
  872. /*
  873.  *----------------------------------------------------------------------
  874.  *
  875.  * FspdevPfsMakeDir --
  876.  *
  877.  *    Make the named directory in a pseudo-filesystem.
  878.  *
  879.  * Results:
  880.  *    A return code from the file server or the RPC.
  881.  *
  882.  * Side effects:
  883.  *    Makes the directory.
  884.  *
  885.  *----------------------------------------------------------------------
  886.  */
  887. /*ARGSUSED*/
  888. ReturnStatus
  889. FspdevPfsMakeDir(prefixHandle, relativeName, argsPtr, resultsPtr, 
  890.         newNameInfoPtrPtr)
  891.     Fs_HandleHeader *prefixHandle;   /* Handle from the prefix table */
  892.     char        *relativeName;   /* The name of the directory to create */
  893.     Address        argsPtr;        /* Ref. to Fs_OpenArgs */
  894.     Address        resultsPtr;        /* == NIL */
  895.     Fs_RedirectInfo **newNameInfoPtrPtr;/* We return this if the server leaves 
  896.                     * its domain during the lookup. */
  897. {
  898.     register Fspdev_ServerIOHandle    *pdevHandlePtr;
  899.     register Fs_OpenArgs        *openArgsPtr;
  900.     Pfs_Request            request;
  901.     register ReturnStatus    status;
  902.     int                resultSize;
  903.  
  904.     pdevHandlePtr = ((Fspdev_ClientIOHandle *)prefixHandle)->pdevHandlePtr;
  905.     openArgsPtr = (Fs_OpenArgs *)argsPtr;
  906.  
  907.     request.hdr.operation = PFS_MAKE_DIR;
  908.     pdevHandlePtr = PfsGetUserLevelIDs(pdevHandlePtr,
  909.                 &openArgsPtr->prefixID, &openArgsPtr->rootID);
  910.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  911.     return(FS_FILE_NOT_FOUND);
  912.     }
  913.     request.param.makeDir = *openArgsPtr;
  914.  
  915.     resultSize = 0;
  916.  
  917.     status = FspdevPseudoStreamLookup(pdevHandlePtr, &request,
  918.         strlen(relativeName) + 1, (Address)relativeName,
  919.         &resultSize, resultsPtr, newNameInfoPtrPtr);
  920.     return(status);
  921. }
  922.  
  923. /*
  924.  *----------------------------------------------------------------------
  925.  *
  926.  * FspdevPfsMakeDevice --
  927.  *
  928.  *    Create a device file in a pseudo-filesystem.
  929.  *
  930.  * Results:
  931.  *    None.
  932.  *
  933.  * Side effects:
  934.  *    Makes a device file.
  935.  *
  936.  *----------------------------------------------------------------------
  937.  */
  938. /*ARGSUSED*/
  939. ReturnStatus
  940. FspdevPfsMakeDevice(prefixHandle, relativeName, argsPtr, resultsPtr,
  941.                    newNameInfoPtrPtr)
  942.     Fs_HandleHeader *prefixHandle;   /* Handle from the prefix table */
  943.     char           *relativeName;   /* The name of the file. */
  944.     Address        argsPtr;        /* Ref. to FsMakeDevArgs */
  945.     Address        resultsPtr;        /* == NIL */
  946.     Fs_RedirectInfo **newNameInfoPtrPtr;/* We return this if the server leaves 
  947.                     * its domain during the lookup. */
  948. {
  949.     register Fspdev_ServerIOHandle    *pdevHandlePtr;
  950.     register Fs_MakeDeviceArgs    *makeDevArgsPtr;
  951.     Pfs_Request            request;
  952.     register ReturnStatus    status;
  953.     int                resultSize;
  954.  
  955.     pdevHandlePtr = ((Fspdev_ClientIOHandle *)prefixHandle)->pdevHandlePtr;
  956.     makeDevArgsPtr = (Fs_MakeDeviceArgs *)argsPtr;
  957.  
  958.     request.hdr.operation = PFS_MAKE_DEVICE;
  959.     pdevHandlePtr = PfsGetUserLevelIDs(pdevHandlePtr,
  960.         &makeDevArgsPtr->open.prefixID, &makeDevArgsPtr->open.rootID);
  961.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  962.     return(FS_FILE_NOT_FOUND);
  963.     }
  964.     request.param.makeDevice = *makeDevArgsPtr;
  965.  
  966.     resultSize = 0;
  967.  
  968.     status = FspdevPseudoStreamLookup(pdevHandlePtr, &request,
  969.         strlen(relativeName) + 1, (Address)relativeName,
  970.         &resultSize, resultsPtr, newNameInfoPtrPtr);
  971.     return(status);
  972. }
  973.  
  974. /*
  975.  *----------------------------------------------------------------------
  976.  *
  977.  * FspdevPfsRemove --
  978.  *
  979.  *    Remove a file served by a pseudo-filesystem server.
  980.  *
  981.  * Results:
  982.  *    None.
  983.  *
  984.  * Side effects:
  985.  *    Does the remove.
  986.  *
  987.  *----------------------------------------------------------------------
  988.  */
  989. /*ARGSUSED*/
  990. ReturnStatus
  991. FspdevPfsRemove(prefixHandle, relativeName, argsPtr, resultsPtr, 
  992.            newNameInfoPtrPtr)
  993.     Fs_HandleHeader   *prefixHandle;    /* Handle from the prefix table */
  994.     char        *relativeName;    /* The name of the file to remove */
  995.     Address        argsPtr;        /* Ref to Fs_LookupArgs */
  996.     Address        resultsPtr;        /* == NIL */
  997.     Fs_RedirectInfo **newNameInfoPtrPtr; /* We return this if the server leaves 
  998.                        its domain during the lookup. */
  999. {
  1000.     register Fspdev_ServerIOHandle    *pdevHandlePtr;
  1001.     register Fs_LookupArgs    *lookupArgsPtr;
  1002.     Pfs_Request            request;
  1003.     register ReturnStatus    status;
  1004.     int                resultSize;
  1005.  
  1006.     pdevHandlePtr = ((Fspdev_ClientIOHandle *)prefixHandle)->pdevHandlePtr;
  1007.     lookupArgsPtr = (Fs_LookupArgs *)argsPtr;
  1008.  
  1009.     request.hdr.operation = PFS_REMOVE;
  1010.     pdevHandlePtr = PfsGetUserLevelIDs(pdevHandlePtr,
  1011.                 &lookupArgsPtr->prefixID, &lookupArgsPtr->rootID);
  1012.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  1013.     return(FS_FILE_NOT_FOUND);
  1014.     }
  1015.     request.param.remove = *lookupArgsPtr;
  1016.  
  1017.     resultSize = 0;
  1018.  
  1019.     status = FspdevPseudoStreamLookup(pdevHandlePtr, &request,
  1020.         strlen(relativeName) + 1, (Address)relativeName,
  1021.         &resultSize, resultsPtr, newNameInfoPtrPtr);
  1022.     return(status);
  1023. }
  1024.  
  1025. /*
  1026.  *----------------------------------------------------------------------
  1027.  *
  1028.  * FspdevPfsRemoveDir --
  1029.  *
  1030.  *    Remove a directory in a pseudo-filesystem.
  1031.  *
  1032.  * Results:
  1033.  *    None.
  1034.  *
  1035.  * Side effects:
  1036.  *    Does the remove.
  1037.  *
  1038.  *----------------------------------------------------------------------
  1039.  */
  1040. /*ARGSUSED*/
  1041. ReturnStatus
  1042. FspdevPfsRemoveDir(prefixHandle, relativeName, argsPtr, resultsPtr, 
  1043.            newNameInfoPtrPtr)
  1044.     Fs_HandleHeader   *prefixHandle;    /* Handle from the prefix table */
  1045.     char        *relativeName;    /* The name of the file to remove */
  1046.     Address        argsPtr;        /* Ref to Fs_LookupArgs */
  1047.     Address        resultsPtr;        /* == NIL */
  1048.     Fs_RedirectInfo **newNameInfoPtrPtr; /* We return this if the server leaves 
  1049.                        its domain during the lookup. */
  1050. {
  1051.     register Fspdev_ServerIOHandle    *pdevHandlePtr;
  1052.     register Fs_LookupArgs    *lookupArgsPtr;
  1053.     Pfs_Request            request;
  1054.     register ReturnStatus    status;
  1055.     int                resultSize;
  1056.  
  1057.     pdevHandlePtr = ((Fspdev_ClientIOHandle *)prefixHandle)->pdevHandlePtr;
  1058.     lookupArgsPtr = (Fs_LookupArgs *)argsPtr;
  1059.  
  1060.     request.hdr.operation = PFS_REMOVE_DIR;
  1061.     pdevHandlePtr = PfsGetUserLevelIDs(pdevHandlePtr,
  1062.                 &lookupArgsPtr->prefixID, &lookupArgsPtr->rootID);
  1063.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  1064.     return(FS_FILE_NOT_FOUND);
  1065.     }
  1066.     request.param.removeDir = *lookupArgsPtr;
  1067.  
  1068.     resultSize = 0;
  1069.  
  1070.     status = FspdevPseudoStreamLookup(pdevHandlePtr, &request,
  1071.         strlen(relativeName) + 1, (Address)relativeName,
  1072.         &resultSize, resultsPtr, newNameInfoPtrPtr);
  1073.     return(status);
  1074. }
  1075.  
  1076. /*
  1077.  *----------------------------------------------------------------------
  1078.  *
  1079.  * FspdevPfsRename --
  1080.  *
  1081.  *    Rename a file is a pseudo-filesystem.
  1082.  *
  1083.  * Results:
  1084.  *    A return status.
  1085.  *
  1086.  * Side effects:
  1087.  *    None.
  1088.  *
  1089.  *----------------------------------------------------------------------
  1090.  */
  1091. ReturnStatus
  1092. FspdevPfsRename(prefixHandle1, relativeName1, prefixHandle2, relativeName2,
  1093.     lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr)
  1094.     Fs_HandleHeader *prefixHandle1;    /* Handle from the prefix table */
  1095.     char *relativeName1;        /* The new name of the file. */
  1096.     Fs_HandleHeader *prefixHandle2;    /* Token from the prefix table */
  1097.     char *relativeName2;        /* The new name of the file. */
  1098.     Fs_LookupArgs *lookupArgsPtr;    /* Contains IDs */
  1099.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server leaves 
  1100.                      * its domain during the lookup. */
  1101.     Boolean *name1ErrorPtr;    /* TRUE if redirect info or other error
  1102.                  * condition if for the first pathname,
  1103.                  * FALSE means error is on second pathname. */
  1104. {
  1105.     return(FspdevPfs2Path(PFS_RENAME, prefixHandle1, relativeName1, prefixHandle2,
  1106.         relativeName2, lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr));
  1107. }
  1108.  
  1109. /*
  1110.  *----------------------------------------------------------------------
  1111.  *
  1112.  * FspdevPfsHardLink --
  1113.  *
  1114.  *    Make a hard link between two files in a pseudo-filesystem.
  1115.  *
  1116.  * Results:
  1117.  *    A return status.
  1118.  *
  1119.  * Side effects:
  1120.  *    None.
  1121.  *
  1122.  *----------------------------------------------------------------------
  1123.  */
  1124. /*ARGSUSED*/
  1125. ReturnStatus
  1126. FspdevPfsHardLink(prefixHandle1, relativeName1, prefixHandle2, relativeName2,
  1127.         lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr)
  1128.     Fs_HandleHeader *prefixHandle1;    /* Token from the prefix table */
  1129.     char *relativeName1;        /* The new name of the file. */
  1130.     Fs_HandleHeader *prefixHandle2;    /* Token from the prefix table */
  1131.     char *relativeName2;        /* The new name of the file. */
  1132.     Fs_LookupArgs *lookupArgsPtr;    /* Contains IDs */
  1133.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server 
  1134.                      * leaves its domain during the lookup*/
  1135.     Boolean *name1ErrorPtr;    /* TRUE if redirect info or other error is
  1136.                  * for first path, FALSE if for the second. */
  1137. {
  1138.     return(FspdevPfs2Path(PFS_HARD_LINK, prefixHandle1, relativeName1,prefixHandle2,
  1139.         relativeName2, lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr));
  1140. }
  1141.  
  1142. /*
  1143.  *----------------------------------------------------------------------
  1144.  *
  1145.  * FspdevPfs2Path --
  1146.  *
  1147.  *    Rename or Hardlink a file is a pseudo-filesystem.  This bundles the
  1148.  *    arguments up for shipment to the server.  The prefix fileIDs are
  1149.  *    mapped to the server's version of them.
  1150.  *
  1151.  * Results:
  1152.  *    A return status.
  1153.  *
  1154.  * Side effects:
  1155.  *    Either a rename or a link.
  1156.  *
  1157.  *----------------------------------------------------------------------
  1158.  */
  1159. ReturnStatus
  1160. FspdevPfs2Path(operation,prefixHandle1, relativeName1, prefixHandle2, relativeName2,
  1161.     lookupArgsPtr, newNameInfoPtrPtr, name1ErrorPtr)
  1162.     Pdev_Op operation;            /* PFS_RENAME or PFS_HARD_LINK */
  1163.     Fs_HandleHeader *prefixHandle1;    /* Handle from the prefix table */
  1164.     char *relativeName1;        /* The new name of the file. */
  1165.     Fs_HandleHeader *prefixHandle2;    /* Token from the prefix table */
  1166.     char *relativeName2;        /* The new name of the file. */
  1167.     Fs_LookupArgs *lookupArgsPtr;    /* Contains IDs */
  1168.     Fs_RedirectInfo **newNameInfoPtrPtr;    /* We return this if the server leaves 
  1169.                      * its domain during the lookup. */
  1170.     Boolean *name1ErrorPtr;    /* TRUE if redirect info or other error
  1171.                  * condition if for the first pathname,
  1172.                  * FALSE means error is on second pathname. */
  1173. {
  1174.     register Fspdev_ServerIOHandle    *pdevHandlePtr;
  1175.     register Fspdev_ServerIOHandle    *pdevHandle2Ptr;
  1176.     Fs_2PathData            *dataPtr;
  1177.     Pfs_Request            request;
  1178.     register ReturnStatus    status;
  1179.  
  1180.     pdevHandlePtr = ((Fspdev_ClientIOHandle *)prefixHandle1)->pdevHandlePtr;
  1181.  
  1182.     request.hdr.operation = operation;
  1183.     pdevHandlePtr = PfsGetUserLevelIDs(pdevHandlePtr,
  1184.                 &lookupArgsPtr->prefixID, &lookupArgsPtr->rootID);
  1185.     if (pdevHandlePtr == (Fspdev_ServerIOHandle *)NIL) {
  1186.     return(FS_FILE_NOT_FOUND);
  1187.     }
  1188.     request.param.rename.lookup = *lookupArgsPtr;
  1189.     if ((prefixHandle2 == (Fs_HandleHeader *)NIL) ||
  1190.     (prefixHandle2->fileID.type != prefixHandle1->fileID.type) ||
  1191.     (prefixHandle2->fileID.major != prefixHandle1->fileID.major) ||
  1192.     (prefixHandle2->fileID.minor != prefixHandle1->fileID.minor)) {
  1193.     /*
  1194.      * Second prefix isn't it the same pseudo-domain. We continue with the
  1195.      * operation in case the first pathname leaves the pseudo-domain.
  1196.      */
  1197.     request.param.rename.prefixID2.type = -1;
  1198.     } else {
  1199.     pdevHandle2Ptr = ((Fspdev_ClientIOHandle *)prefixHandle2)->pdevHandlePtr;
  1200.     request.param.rename.prefixID2 = pdevHandle2Ptr->userLevelID;
  1201.     }
  1202.     dataPtr = (Fs_2PathData *)malloc(sizeof(Fs_2PathData));
  1203.     (void)strcpy(dataPtr->path1, relativeName1);
  1204.     (void)strcpy(dataPtr->path2, relativeName2);
  1205.  
  1206.     status = FspdevPseudoStream2Path(pdevHandlePtr, &request, dataPtr,
  1207.         name1ErrorPtr, newNameInfoPtrPtr);
  1208.     free((Address)dataPtr);
  1209.     return(status);
  1210. }
  1211.